#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>

const char *globalString1 = "a";
const char *globalString2 = "b";
bool isATurn = false;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

// class Foo {
// public:
//     Foo() {
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_cond2,nullptr);
//         pthread_cond_init(&_cond3,nullptr);
//     }

//     void first(function<void()> printFirst) {

//         // printFirst() outputs "first". Do not change or remove this line.
//         pthread_mutex_lock(&_mutex);
//         printFirst();
//         isOturn=true;
//         pthread_cond_signal(&_cond2);//唤醒second
//         pthread_mutex_unlock(&_mutex);
//     }

//     void second(function<void()> printSecond) {

//         // printSecond() outputs "second". Do not change or remove this line.
//         pthread_mutex_lock(&_mutex);
//         while(!isOturn)//当1在执行时2要等
//             pthread_cond_wait(&_cond2,&_mutex);
//         printSecond();
//         isSturn=true;
//         pthread_cond_signal(&_cond3);//唤醒third
//         pthread_mutex_unlock(&_mutex);
//     }

//     void third(function<void()> printThird) {

//         // printThird() outputs "third". Do not change or remove this line.
//         pthread_mutex_lock(&_mutex);
//         while(!isSturn)//当2在执行时3要等
//             pthread_cond_wait(&_cond3,&_mutex);
//         printThird();
//         pthread_mutex_unlock(&_mutex);
//     }
//     ~Foo(){
//         pthread_mutex_destroy(&_mutex);

//         pthread_cond_destroy(&_cond2);
//         pthread_cond_destroy(&_cond3);
//     }
//     private:
//     pthread_mutex_t _mutex;

//     pthread_cond_t _cond2;
//     pthread_cond_t _cond3;
//     bool isOturn=false;
//     bool isSturn=false;
// };

// bug:超时
// https://leetcode.cn/problems/building-h2o/
// class H2O {
// public:
//     H2O() {
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_condH,nullptr);
//         pthread_cond_init(&_condO,nullptr);
//     }
//     void hydrogen(function<void()> releaseHydrogen) {

//         // releaseHydrogen() outputs "H". Do not change or remove this line.
//         pthread_mutex_lock(&_mutex);

//         while(fullHydrogen())// 如果H的数量够了，那就让H先wait
//             pthread_cond_wait(&_condH,&_mutex);
//         releaseHydrogen();
//         hydrogenCount++;
//         if(get()){
//             oxygenCount=0;
//             hydrogenCount=0;
//         }

//         // pthread_cond_signal(&_condO);
//         pthread_cond_broadcast(&_condO);
//         pthread_mutex_unlock(&_mutex);
//     }

//     void oxygen(function<void()> releaseOxygen) {

//         // releaseOxygen() outputs "O". Do not change or remove this line.
//         pthread_mutex_lock(&_mutex);

//         while(fullOxygen())// 如果O的数量够了，那就让O先wait
//             pthread_cond_wait(&_condO,&_mutex);
//         releaseOxygen();
//         oxygenCount++;
//         if(get()){
//             oxygenCount=0;
//             hydrogenCount=0;
//         }
//         // pthread_cond_signal(&_condH);
//         pthread_cond_broadcast(&_condH);
//         pthread_mutex_unlock(&_mutex);
//     }
//     ~H2O(){
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_condH);
//         pthread_cond_destroy(&_condO);
//     }
//     private:
//     bool fullOxygen(){
//         return oxygenCount==1;
//     }
//     bool fullHydrogen(){
//         return hydrogenCount==2;
//     }
//     bool get(){
//         return fullOxygen()&&fullHydrogen();
//     }
//     private:
//     pthread_mutex_t _mutex;
//     pthread_cond_t _condH;
//     pthread_cond_t _condO;
//     int hydrogenCount;
//     int oxygenCount;
// };
void *threadroutine1(void *args)
{
  pthread_detach(pthread_self());
  while (true)
  {
    /* code */
    pthread_mutex_lock(&lock);
    while (!isATurn)
      pthread_cond_wait(&cond, &lock);
    std::cout << "我是线程" << globalString1 << std::endl;
    isATurn = false;
    pthread_cond_signal(&cond); // 通知线程b可以打印
    pthread_mutex_unlock(&lock);
    sleep(1);
  }
}

void *threadroutine2(void *args)
{
  pthread_detach(pthread_self());
  while (true)
  {
    /* code */
    pthread_mutex_lock(&lock);
    while (isATurn)
      pthread_cond_wait(&cond, &lock);
    std::cout << "我是线程" << globalString2 << std::endl;
    isATurn = true;
    pthread_cond_signal(&cond); // 通知线程a可以打印
    pthread_mutex_unlock(&lock);
    sleep(1);
  }
}

int main()
{
  pthread_t tid1;
  pthread_t tid2;

  pthread_create(&tid1, nullptr, threadroutine1, (void *)globalString1);
  pthread_create(&tid2, nullptr, threadroutine2, (void *)globalString2);
  while (1)
    ;
}